

#include "SD_FileMan.h"

#include "ff.h"

#define MAXSTSFILEEACHDIR	128

DIR 		FM_Dir;
FILINFO 	FM_FileInfo;


//------------------------ functions ---------------------------------------------------------
void FM_Init(FILEMAN_STRUCT *fm,uint8_t fileTN,uint32_t fileS,uint8_t fileNameID)
{
	fm->fileTotalNum  = fileTN;
	fm->fileSize      = fileS;
	
	fm->w_FileIndex   = 0xFF;
	fm->w_FilePtr     = 0xFFFFFFFF;
	fm->r_FileIndex   = 0xFF;
	fm->r_FilePtr     = 0xFFFFFFFF;
	
	fm->lastToRead    = 0;
	
	fm->loadSDInfo    = 0;
	fm->transSize     = 1024*5;
	
	fm->data_FileName[0]  = '0';
	fm->data_FileName[1]  = ':';
	fm->data_FileName[2]  = '/';
	fm->data_FileName[3]  = fileNameID;
	fm->data_FileName[4]  = '0';
	fm->data_FileName[5]  = '0';
	fm->data_FileName[6]  = '0';
	fm->data_FileName[7]  = '.';
	fm->data_FileName[8]  = 'S';
	fm->data_FileName[9]  = 'T';
	fm->data_FileName[10] = 'S';
	fm->data_FileName[11] = 0;
	
	fm->Info_FileName[0]  = '0';
	fm->Info_FileName[1]  = ':';
	fm->Info_FileName[2]  = '/';
	fm->Info_FileName[3]  = fileNameID;
	fm->Info_FileName[4]  = '.';
	fm->Info_FileName[5]  = 'i';
	fm->Info_FileName[6]  = 'n';
	fm->Info_FileName[7]  = 'f';
	fm->Info_FileName[8]  = 0;
	
	return;
}

uint8_t* FM_Name(FILEMAN_STRUCT *fm,uint8_t i)
{
	fm->data_FileName[4] = '0' + (i%1000/100);
	fm->data_FileName[5] = '0' + (i%100/10);
	fm->data_FileName[6] = '0' + (i%10/1);
	return fm->data_FileName;
}

uint8_t FileIndexAdd(FILEMAN_STRUCT *fm,uint8_t index)
{
	index++;
	return (index%fm->fileTotalNum);
}

uint32_t get32_Little_endian(uint8_t *buf)
{
	return ( buf[0] + 
			(buf[1] <<  8) + 
			(buf[2] << 16) + 
			(buf[3] << 24));
}

void set32_Little_endian(uint8_t *buf,uint32_t data)
{
	buf[0] = (data >> 0) & 0xff;
	buf[1] = (data >> 8) & 0xff;
	buf[2] = (data >>16) & 0xff;
	buf[3] = (data >>24) & 0xff;
	return;
}
//------------------------ initialization --------------------------------
uint8_t FM_Get_WFileInfo(FILEMAN_STRUCT *fm)
{
	uint8_t res = 0,*buf;
	uint32_t f_size = 0;
	
	if(fm->loadSDInfo)
		return 0;
	buf = fm->SdInfo_FileBuf;
	res = FindSdFile(buf,0,10,&f_size,fm->Info_FileName);
	
	if(!res && f_size == 10)
	{
		fm->w_FileIndex = buf[0];
		fm->w_FilePtr = get32_Little_endian(buf+1);
		fm->r_FileIndex = buf[5];
		fm->r_FilePtr = get32_Little_endian(buf+6);
	}
	else
	{
		fm->w_FileIndex = 0;
		fm->w_FilePtr = 0;
		fm->r_FileIndex = 0xff;
		fm->r_FilePtr = 0xffffffff;
	}
	fm->loadSDInfo = 1;
	return res;
}



uint8_t FM_SaveInfoFile(FILEMAN_STRUCT *fm)
{
	uint8_t res = 0,*infobuf;
	uint32_t f_size;
	
	infobuf = fm->SdInfo_FileBuf;
	infobuf[0] = fm->w_FileIndex;
	set32_Little_endian(&infobuf[1],fm->w_FilePtr);
	
	infobuf[5] = fm->r_FileIndex;
	set32_Little_endian(&infobuf[6],fm->r_FilePtr);
		
	res = WriteSdFile(infobuf,0,10,&f_size,fm->Info_FileName);
	return res;
}


void FM_SetReadForm(FILEMAN_STRUCT *fm,uint8_t readTotal,uint32_t transS,uint32_t maxS)
{
	FM_Get_WFileInfo(fm);
	if(readTotal == 0x55)
	{
		fm->r_FileIndex = 0xff;
		fm->r_FilePtr = 0xffffffff;
	}
	if(transS <= maxS)
		fm->transSize = transS;
	else
		fm->transSize = maxS;
	
	return;
}
//----------------------- write in --------------------------------------------------------
uint8_t FM_SaveDataToFile(FILEMAN_STRUCT *fm,uint8_t *buf, uint32_t len,uint32_t *bytesWritten)
{
	uint8_t res = 0;
	
	FM_Get_WFileInfo(fm);
	//if eixti
	if(fm->w_FilePtr == 0xffffffff || fm->w_FileIndex >= fm->fileTotalNum)
		return 0xff;
	
	res = WriteSdFile(buf,fm->w_FilePtr,len,bytesWritten,FM_Name(fm,fm->w_FileIndex));
	if(res)
		return res;
	
	if(len != *bytesWritten)
		return 0xfe;
	
	fm->w_FilePtr += len;
	if(fm->w_FilePtr >= fm->fileSize)
	{
		fm->w_FilePtr = 0;
		fm->w_FileIndex = FileIndexAdd(fm,fm->w_FileIndex);
		
		if(fm->w_FileIndex == fm->r_FileIndex)
		{
			fm->r_FileIndex = 0xff;
			fm->r_FilePtr = 0xffffffff;
		}
	}
	
	return FM_SaveInfoFile(fm);
}
//------------------------ read out  --------------------------------------------------------
uint8_t FM_FindNextFileForRead(FILEMAN_STRUCT *fm)
{
	uint8_t indextmp;
	indextmp = FileIndexAdd(fm,fm->r_FileIndex);
	
	if(indextmp == fm->w_FileIndex)
	{
		if(fm->w_FilePtr == 0)
		{
			return 0;
		}
		fm->lastToRead = 1;
		fm->r_FilePtr = 0;
		fm->r_FileIndex = indextmp;
		fm->w_FilePtr = 0;
		fm->w_FileIndex = FileIndexAdd(fm,fm->w_FileIndex);
	}
	else
	{
		fm->lastToRead = 0;
		fm->r_FilePtr = 0;
		fm->r_FileIndex = indextmp;
	}
	return 1;
}
//when return != 0, ignore para len
uint8_t FM_ReadFile(FILEMAN_STRUCT *fm,uint8_t *buf, uint32_t *len,uint32_t toRead)
{
	uint8_t res = 0;
	uint32_t f_size = 0;
	
	*len = 0;
	FM_Get_WFileInfo(fm);
	
	if(fm->w_FilePtr == 0xffffffff || fm->w_FileIndex >= fm->fileTotalNum)
		return 0xFF;
	
	if(fm->r_FileIndex == 0xff && fm->r_FilePtr == 0xffffffff)
	{
		fm->r_FilePtr = 0;
		fm->r_FileIndex = FileIndexAdd(fm,fm->w_FileIndex);
		fm->lastToRead = 0;
	}
	
	
	res = GetSdFileStats(&f_size,FM_Name(fm,fm->r_FileIndex));
	if(res||(!res&&f_size <= fm->r_FilePtr))
	{
		if(fm->lastToRead)
		{
			FM_SaveInfoFile(fm);
			fm->lastToRead = 0;
			return 0xFF;
		}
		else if(!FM_FindNextFileForRead(fm))
		{
			FM_SaveInfoFile(fm);
			return 0xFF;
		}
		else
		{
			return 0;
		}
		
	}
	
	if(toRead > 512 * 127)
		toRead = 512 * 127;
	//have file , check length , and read ,
	res = FindSdFile(buf,fm->r_FilePtr,toRead,len,FM_Name(fm,fm->r_FileIndex));
	if(res)
	{
		return res;
	}
	else
	{
		fm->r_FilePtr += *len;
	}
	
	return 0;
}

uint8_t FM_readAllFileStatus(FILEMAN_STRUCT *fm,uint8_t *buf,uint32_t *len)
{
	uint32_t i,f_size;
	
	*len = 10;
	
	for(i=0;i<*len;i++)
		buf[i] = 0;
	
	return FindSdFile(buf,0,10,&f_size,fm->Info_FileName);
}
/*
 * Delete an existing file or directory(shoule be empty). 
*/
uint8_t FM_Delete(uint8_t *path)
{
	uint8_t res = 0;
	
	res = f_unlink((const TCHAR *)path);

	return res;
}

/*
 * creat a directory. 
*/
uint8_t FM_CreateDir(uint8_t *path)
{
	uint8_t res = 0;
	
	res = f_mkdir((const TCHAR *)path);
	
	return res;
}

/*
 * oldname is ok with whole path in it.
 * newname not including the path.
*/
uint8_t FM_RenameFile(uint8_t *oldname,uint8_t* newname)
{
	uint8_t res = 0;
	
	res = f_rename((const TCHAR *)oldname,(const TCHAR *)newname);

	return res;
}

uint8_t FM_readDirItems(uint8_t *name,uint8_t *readbuf)
{
	uint8_t res = 0,res2 = 0,i;
	uint16_t len=0;
	
	res = f_opendir(&FM_Dir, (const TCHAR *)name);
	while((!res)&&(!res2))
	{
		res2 = f_readdir(&FM_Dir,&FM_FileInfo);
		if(!res2)
		{
			for(i = 0;i<13&&FM_FileInfo.fname[i]!=0&&len<1000;i++)
			{
				readbuf[len++] = FM_FileInfo.fname[i];
			}
			if(len==1000)
				break;
			if(i==0)
				break;
			readbuf[len++]  = 0x0D;
			readbuf[len++]  = 0x0A;
		}
	}
	
	readbuf[len] = 0;
	
	if(!res)
		f_closedir(&FM_Dir);
	return res;
}


uint8_t FM_readFreeSectors(uint8_t *path,uint8_t *buf)
{
	uint8_t res = 0;
	FATFS *fs;
	DWORD fre_clust, fre_sect;//, tot_sect;
	
	res = f_getfree((const TCHAR *)path, &fre_clust,&fs);
	
	//tot_sect = (fs->max_clust - 2) * fs->csize;
	fre_sect =fre_clust * fs->csize;
	buf[0] = (fre_sect>> 0)&0xff;
	buf[1] = (fre_sect>> 8)&0xff;
	buf[2] = (fre_sect>>16)&0xff;
	buf[3] = (fre_sect>>24)&0xff;
	
	return res;
}
///////////////////////////////////////////////////////////////////////////////////
//                         SD Files Manage(Directory Mode)
///////////////////////////////////////////////////////////////////////////////////

//EOF


















